/*!
 *	\file myfs.h
 *
 *	в данном файле хранятся основные структуры, используемые
 *	файловой системой, и макросы
 *
 */

#ifndef MYFS_H
#define MYFS_H

/*! у каждой файловой системы должно быть своё "магическое" число */
#define MYFS_MAGIC 0x19980122
#define MYFS_DFLT_BLOCKSIZE 4096 /*!< размер блока файловой системы */

#define MYFS_ROOT_INODE(sb) ((sb)->s_first_nonmeta_inode) /*!< возвращает номер ROOT и-узла */

#define MYFS_SUPER_BLOCK 1	/*!< номер блока, в котором находится суперблок файловой системы */
#define MYFS_INODE_BM_BLOCK 2	/*!< номер блока, в котором находится карта битов файловой сиистемы */

#define MYFS_MAX_NAME_LEN 12    /*!< максимальная длина имени файла или директории */

#include <linux/types.h>
#include <linux/magic.h>
#include <linux/fs.h>

#ifdef __KERNEL__		/* код виден только в пространстве ядра */

/*! данная структура используется для хранения дополнительной информации о и-узле */
struct myfs_inode_info {
	struct inode vfs_inode;
	__u32 flags;
	__u32 state;
	__u32 i_data[1];
} ;

#endif	/* __KERNEL__ */

/*! данной структурой представлен и-узел файловой системы myfs */
struct myfs_inode {
	__u32 i_mode;		/*!< данное поле указывает принадлежит данный и-узел директории или файлу */
	__u32 i_num_links;	/*!< количество ссылок */
	__u32 i_uid;		/*!< id пользователя, которому принадлежит данный и-узел */
	__u32 i_gid;		/*!< id группы, которой принадлежит данный и-узел */
	__u32 i_size;		/*!< размер данных, на которые указывает данный и-узел */
	struct timespec atime;  /*!< в данной структуре хранится время последнего доступа к содержимому и-узла */
	struct timespec ctime;  /*!< в данной структуре хранится время создания  и-узла */
	struct timespec mtime;  /*!< в данной структуре хранится время последнего изменения содержимого и-узла */
	__u32 data[1];		/*!< в данном поле хранится номер и-узла */
};

/*! данная структура используется для хранения дополнительной информации о суперблоке */
struct myfs_sb_info {
	struct myfs_super_block *s_mfs;		/*!< ссылка на суперблок файловой системы myfs */
	struct buffer_head *s_bh;		/*!< ссылка на буфер, в котором хранится содержимое суперблока myfs */ 
	struct buffer_head *inode_bitmap;	/*!< ссылка на буфер, в котором хранится содержимое карты битов */
	__u32 s_free_inodes_count;		/*!< количество свободных и-узлов */
	__u32 s_inodes_count;			/*!< общее количество и-узлов */
	__u32 s_first_nonmeta_inode;		/*!< номер и-узла, пренадлежащего ROOT-директории */
};

/*! данной структурой представлен суперблок файловой системы myfs */
struct myfs_super_block {
	__u32 s_magic;				/*!< "магическое число" файловой системы myfs */
	__u32 s_inodes_count;			/*!< общее количество и-узлов */
	__u32 s_free_inodes_count;		/*!< количество свободных и-узлов */
	__u32 s_blocksize;			/*!< размер блока */
	__u32 s_free_blocks_count;		/*!< количество свободных блоков */
	__u32 s_first_nonmeta_inode;		/*!< номер и-узла, пренадлежащего ROOT-директории */
};

/*! данной структурой представлен элемент каталога файловой системы myfs */
struct myfs_dir_entry {
	__u32 inode;				
      	__u32 name_len;				/*!< длина имени элемента директории */
      	__u32 file_type;			/*!< тип элемента директории */
	__u32 rec_len;				/*!< длина записи элемента директории */
	char name[MYFS_MAX_NAME_LEN];		/*!< имя элемента директории */
} ;

#define MYFS_NAME_ROUND 3	/*!< используется при получении длины записи элемента каталога */

/*! 
 *	функциия возвращает длину записи элемента директории.
 *	в качестве параметра функции передается структура,
 *	представляющая элемент директории
 */
static inline __u32 calc_rec_len(struct myfs_dir_entry *dirent)
{
	return (dirent->name_len + (sizeof(struct myfs_dir_entry) - MYFS_MAX_NAME_LEN) +
			MYFS_NAME_ROUND) & ~MYFS_NAME_ROUND; 
}

/*!
 *	функция возвращает длину записи элемента директории.
 *	в качестве параметра функции передается длина имени
 *	элемента директории
 */
static inline __u32 calc_reclen_from_len(unsigned int name_len)
{
	return (name_len + (sizeof(struct myfs_dir_entry) - MYFS_MAX_NAME_LEN) +
			MYFS_NAME_ROUND) & ~MYFS_NAME_ROUND; 
}

#ifdef __KERNEL__	/* код виден только в пространстве ядра */

static inline struct myfs_sb_info *MYFS_SB(struct super_block *sb)
{
	return sb->s_fs_info;
}

static inline struct myfs_inode_info *MYFS_I(struct inode *inode)
{
	return container_of(inode, struct myfs_inode_info, vfs_inode);
}

extern const struct address_space_operations myfs_aops;
extern const struct file_operations myfs_dir_operations;
extern const struct file_operations myfs_file_operations;
extern const struct inode_operations myfs_file_inode_operations;
extern const struct inode_operations myfs_dir_inode_operations;
extern const struct inode_operations myfs_symlink_inode_operations;

#endif /* __KERNEL__ */
#endif /* MYFS_H */
